package com.university.evaluation.utils;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.Date;
import java.util.TimeZone;

public class DateUtils {

    // 常用日期时间格式
    public static final String PATTERN_DATE = "yyyy-MM-dd";
    public static final String PATTERN_TIME = "HH:mm:ss";
    public static final String PATTERN_DATETIME = "yyyy-MM-dd HH:mm:ss";
    public static final String PATTERN_DATETIME_SIMPLE = "yyyyMMddHHmmss";
    public static final String PATTERN_DATETIME_MILLIS = "yyyy-MM-dd HH:mm:ss.SSS";
    public static final String PATTERN_YEAR_MONTH = "yyyy-MM";
    public static final String PATTERN_MONTH_DAY = "MM-dd";

    // 默认时区
    private static final TimeZone DEFAULT_TIMEZONE = TimeZone.getTimeZone("Asia/Shanghai");

    // 获取当前日期时间
    public static Date now() {
        return new Date();
    }

    // 获取当前日期（不含时间）
    public static Date today() {
        LocalDate localDate = LocalDate.now();
        return localDateToDate(localDate);
    }

    // 格式化日期时间
    public static String format(Date date, String pattern) {
        if (date == null) {
            return null;
        }
        SimpleDateFormat sdf = new SimpleDateFormat(pattern);
        sdf.setTimeZone(DEFAULT_TIMEZONE);
        return sdf.format(date);
    }

    // 格式化当前日期时间
    public static String formatNow(String pattern) {
        return format(now(), pattern);
    }

    // 解析日期时间字符串
    public static Date parse(String dateStr, String pattern) {
        if (dateStr == null || dateStr.isEmpty()) {
            return null;
        }
        try {
            SimpleDateFormat sdf = new SimpleDateFormat(pattern);
            sdf.setTimeZone(DEFAULT_TIMEZONE);
            return sdf.parse(dateStr);
        } catch (ParseException e) {
            throw new RuntimeException("日期解析错误: " + dateStr, e);
        }
    }

    // 计算两个日期之间的天数差
    public static long daysBetween(Date startDate, Date endDate) {
        if (startDate == null || endDate == null) {
            throw new IllegalArgumentException("日期不能为空");
        }
        long diff = endDate.getTime() - startDate.getTime();
        return diff / (1000 * 60 * 60 * 24);
    }

    // 计算两个日期之间的小时差
    public static long hoursBetween(Date startDate, Date endDate) {
        if (startDate == null || endDate == null) {
            throw new IllegalArgumentException("日期不能为空");
        }
        long diff = endDate.getTime() - startDate.getTime();
        return diff / (1000 * 60 * 60);
    }

    // 计算两个日期之间的分钟差
    public static long minutesBetween(Date startDate, Date endDate) {
        if (startDate == null || endDate == null) {
            throw new IllegalArgumentException("日期不能为空");
        }
        long diff = endDate.getTime() - startDate.getTime();
        return diff / (1000 * 60);
    }

    // 在日期上增加天数
    public static Date addDays(Date date, int days) {
        if (date == null) {
            return null;
        }
        LocalDateTime localDateTime = dateToLocalDateTime(date);
        localDateTime = localDateTime.plusDays(days);
        return localDateTimeToDate(localDateTime);
    }

    // 在日期上增加小时数
    public static Date addHours(Date date, int hours) {
        if (date == null) {
            return null;
        }
        LocalDateTime localDateTime = dateToLocalDateTime(date);
        localDateTime = localDateTime.plusHours(hours);
        return localDateTimeToDate(localDateTime);
    }

    // 在日期上增加分钟数
    public static Date addMinutes(Date date, int minutes) {
        if (date == null) {
            return null;
        }
        LocalDateTime localDateTime = dateToLocalDateTime(date);
        localDateTime = localDateTime.plusMinutes(minutes);
        return localDateTimeToDate(localDateTime);
    }

    // 获取日期的年份
    public static int getYear(Date date) {
        if (date == null) {
            return 0;
        }
        LocalDate localDate = dateToLocalDate(date);
        return localDate.getYear();
    }

    // 获取日期的月份（1-12）
    public static int getMonth(Date date) {
        if (date == null) {
            return 0;
        }
        LocalDate localDate = dateToLocalDate(date);
        return localDate.getMonthValue();
    }

    // 获取日期的日份（1-31）
    public static int getDay(Date date) {
        if (date == null) {
            return 0;
        }
        LocalDate localDate = dateToLocalDate(date);
        return localDate.getDayOfMonth();
    }

    // 获取日期的小时（0-23）
    public static int getHour(Date date) {
        if (date == null) {
            return 0;
        }
        LocalDateTime localDateTime = dateToLocalDateTime(date);
        return localDateTime.getHour();
    }

    // 获取日期的分钟（0-59）
    public static int getMinute(Date date) {
        if (date == null) {
            return 0;
        }
        LocalDateTime localDateTime = dateToLocalDateTime(date);
        return localDateTime.getMinute();
    }

    // 获取日期的秒数（0-59）
    public static int getSecond(Date date) {
        if (date == null) {
            return 0;
        }
        LocalDateTime localDateTime = dateToLocalDateTime(date);
        return localDateTime.getSecond();
    }

    // Date转LocalDate
    public static LocalDate dateToLocalDate(Date date) {
        if (date == null) {
            return null;
        }
        Instant instant = date.toInstant();
        ZoneId zoneId = DEFAULT_TIMEZONE.toZoneId();
        return instant.atZone(zoneId).toLocalDate();
    }

    // Date转LocalDateTime
    public static LocalDateTime dateToLocalDateTime(Date date) {
        if (date == null) {
            return null;
        }
        Instant instant = date.toInstant();
        ZoneId zoneId = DEFAULT_TIMEZONE.toZoneId();
        return instant.atZone(zoneId).toLocalDateTime();
    }

    // LocalDate转Date
    public static Date localDateToDate(LocalDate localDate) {
        if (localDate == null) {
            return null;
        }
        ZoneId zoneId = DEFAULT_TIMEZONE.toZoneId();
        Instant instant = localDate.atStartOfDay(zoneId).toInstant();
        return Date.from(instant);
    }

    // LocalDateTime转Date
    public static Date localDateTimeToDate(LocalDateTime localDateTime) {
        if (localDateTime == null) {
            return null;
        }
        ZoneId zoneId = DEFAULT_TIMEZONE.toZoneId();
        Instant instant = localDateTime.atZone(zoneId).toInstant();
        return Date.from(instant);
    }

    // 判断是否为今天
    public static boolean isToday(Date date) {
        if (date == null) {
            return false;
        }
        LocalDate localDate = dateToLocalDate(date);
        return localDate.isEqual(LocalDate.now());
    }

    // 判断是否为昨天
    public static boolean isYesterday(Date date) {
        if (date == null) {
            return false;
        }
        LocalDate localDate = dateToLocalDate(date);
        return localDate.isEqual(LocalDate.now().minusDays(1));
    }

    // 判断是否为明天
    public static boolean isTomorrow(Date date) {
        if (date == null) {
            return false;
        }
        LocalDate localDate = dateToLocalDate(date);
        return localDate.isEqual(LocalDate.now().plusDays(1));
    }

    // 判断两个日期是否是同一天
    public static boolean isSameDay(Date date1, Date date2) {
        if (date1 == null || date2 == null) {
            return false;
        }
        LocalDate localDate1 = dateToLocalDate(date1);
        LocalDate localDate2 = dateToLocalDate(date2);
        return localDate1.isEqual(localDate2);
    }

    // 判断一个日期是否在另一个日期之前
    public static boolean isBefore(Date date1, Date date2) {
        if (date1 == null || date2 == null) {
            throw new IllegalArgumentException("日期不能为空");
        }
        return date1.before(date2);
    }

    // 判断一个日期是否在另一个日期之后
    public static boolean isAfter(Date date1, Date date2) {
        if (date1 == null || date2 == null) {
            throw new IllegalArgumentException("日期不能为空");
        }
        return date1.after(date2);
    }

    // 获取当前时间戳（毫秒）
    public static long currentTimeMillis() {
        return System.currentTimeMillis();
    }

    // 获取当前时间戳（秒）
    public static long currentTimeSeconds() {
        return System.currentTimeMillis() / 1000;
    }

}